package zx.lrn.notes.basic_grammer.about_collections;

import java.io.File;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * @ClassName: ConcurrentHashMapDemo
 * @Description: 并发安全集合-ConcurrentHashMap的批操作
 *               ConcurrentHashMap的批操作共有三大类：search、foreach、reduce，每类操作都有4个版本，分别处理键、值、键值对、Map.Entry对象
 *               search：为每个元素应用一个函数，当函数返回非null时，搜索结束，返回函数的结果 foreach：为每个元素应用一个函数 reduce：归约，即组合所有键和值
 *               上述三种操作都可以以并行方式运行，需要指定参数化阈值，该阈值表示任务规模，当元素数量>阈值时，就会并行完成批操作
 * @Author: zhaoxuan
 * @Date: 2020/3/11 0:03
 **/
public class ConcurrentHashMapBatch {

    public static void main(String[] args) throws Exception {
        ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap();
        IntStream.rangeClosed(1, 10000).forEach(i -> map.put(i + "", i));
        System.out.println("**********************");
        // search,找出第一个v>8590的value，元素数量10000 > 阈值100，所以并行查找，结果一般都不是8591
        Integer result = map.searchValues(100, v -> v > 8590 ? v : null);
        // foreach 和 reduce 可以添加一个转换器，当转换器返回null时，此元素将被pass，因此可以用做过滤器
        map.forEachValue(100, v -> v % 3333 == 0 ? v : null, System.out::println);
        // reduce reduce需要提供一个操作op，该op对前两个元素使用后，将结果与第三个元素再次做该操作
        // 即a op b op c op d op e ...... ，因此当并行reduce时需要考虑op操作是否可以乱序，
        // 例：连加可以 1+2+3+4+5 = 1+(2+3)+(4+5)
        // 例：连减不行 1-2-3-4-5 != 1-(2-3)-(4-5)
        System.out.println(map.reduceValues(10000, Integer::sum));
    }
}
